package ss.pku.jsa.type.inference;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import ss.pku.jsa.type.constraint.solver.Native;


@SuppressWarnings({"unchecked","rawtypes"})
public class QualGate {
	private int nativeIndex;
	boolean forward;
	boolean backward;
	
	List<String> quals = new LinkedList();

	public static QualGate EMPTY = new QualGate(true, true);

	static {
		Native.qualGateSetAll(EMPTY.nativeIndex, true);
	}

	public QualGate(boolean forward, boolean backward) {
		this.nativeIndex = Native.allocQGate(forward, backward);
		this.forward = forward;
		this.backward = backward;
	}

	public boolean equals(Object o) {
		if (!(o instanceof QualGate))
			return false;
		QualGate q = (QualGate) o;
		return (this.nativeIndex == q.nativeIndex)
				|| ((this.forward == q.forward)
						&& (this.backward == q.backward) && (this.quals
						.equals(q.quals)));
	}

	public int hashcode() {
		int ret = 0;
		for (String q : this.quals)
			ret += q.hashCode();
		return ret;
	}

	public void addQual(Qualifier q, boolean allow) {
		Native.addQualToGate(this.nativeIndex, q.getNativeIndex(), allow);
		this.quals.add((allow ? "" : "X") + q);
	}

	public void setAll(boolean allow) {
		Native.qualGateSetAll(this.nativeIndex, allow);
		this.quals.add((allow ? "" : "X") + "<all>");
	}

	public String toString() {
		if ((this.backward) && (this.forward) && (this.quals.isEmpty()))
			return "";
		StringBuffer ret = new StringBuffer((this.backward ? "<-" : "|-")
				+ (this.forward ? ">" : "|"));
		ret.append("(");
		for (Iterator i = this.quals.iterator(); i.hasNext();) {
			ret.append(i.next().toString());
			if (!i.hasNext())
				continue;
			ret.append(", ");
		}
		ret.append(")");
		return ret.toString();
	}

	public int getNativeIndex() {
		return this.nativeIndex;
	}
}
